# -*- coding: utf-8 -*-
# created on 2016/5/5
import itertools

from sympy import *
from mathsolver.functions.sympy_utils import safe_degree


# 判断一元一次方程: ax+b=0
def yicifangcheng_judge(eq, target_symbol):
    answer = False
    eq_daoshu = diff(eq, target_symbol)
    if not eq_daoshu.has(target_symbol):
        answer = True
    return answer


# 判断一元二次方程: ax^2+bx+c=0
def ercifangcheng_judge(eq, target_symbol):
    answer = False
    eq_daoshu = diff(eq, target_symbol)
    if eq_daoshu.has(target_symbol):
        if yicifangcheng_judge(eq_daoshu, target_symbol):
            answer = True
    return answer


# 判断一元一次方程: ax+b=0
def jueduizhifangcheng_judge(eq):
    answer = False
    if isinstance(eq, Abs):
        answer = True
    if "Abs" in eq:
        print(1)
    return answer


# 判断二元一次方程: a*x+b*y+c=0
def eryuanyicifangcheng_judge(eq):
    answer = True
    syms = eq.free_symbols

    if len(syms) != 2:
        answer = False
    else:
        for a1, a2 in itertools.combinations(syms, 2):
            if eq.has(a1 * a2):
                answer = False
        for sym in syms:
            if safe_degree(eq, sym) != 1:
                answer = False
                break
    return answer


# 判断二元一次方程组:
def eryuanyicifangchengzu_judge(eqs):
    answer = False
    if len(eqs) == 2:
        eq1 = eqs[0][0] - eqs[0][1]
        eq2 = eqs[1][0] - eqs[1][1]
        eq1_symbols = eq1.free_symbols
        eq2_symbols = eq2.free_symbols
        if eq1_symbols.issubset(eq2_symbols) or eq2_symbols.issubset(eq1_symbols):
            if len(eq1_symbols) == 2 and len(eq2_symbols) == 2:
                if eryuanyicifangcheng_judge(eq1) and eryuanyicifangcheng_judge(eq2):
                    answer = True
            elif len(eq1_symbols) == 1 and len(eq2_symbols) == 2:
                target_symbol = list(eq1_symbols)[0]
                if yicifangcheng_judge(eq1, target_symbol) and eryuanyicifangcheng_judge(eq2):
                    answer = True
            elif len(eq1_symbols) == 2 and len(eq2_symbols) == 1:
                target_symbol = list(eq2_symbols)[0]
                if yicifangcheng_judge(eq2, target_symbol) and eryuanyicifangcheng_judge(eq1):
                    answer = True
        elif len(eq1_symbols) == 1 and len(eq2_symbols) == 1:
            answer = True
    return answer


# 判断分式方程
def fenshi_judge(eq, target_symbol):
    answer = False
    if eq.is_Mul:
        if eq.args[1].is_Pow and eq.args[1].args[1] == -1:
            answer = True
    elif eq.is_Pow and eq.args[1] == -1:
        answer = True
    elif eq.is_Add:
        target_index = []
        for arg in eq.args:
            if arg.has(target_symbol):
                if arg.is_Mul:
                    if arg.args[1].is_Pow and arg.args[1].args[1] == -1:
                        target_index.append(1)
                    else:
                        target_index.append(0)
                elif arg.is_Pow:
                    if arg.args[1] == -1:
                        target_index.append(1)
                    else:
                        target_index.append(0)
        if sum(target_index) > 0:
            answer = True
    return answer


# 判断方程形式
# 递归化简 参数为表达式
# flag [0]-type1  [1]-分式方程  [2]-指数  [3]-根号   [4]-绝对值   [5]-对数函数  [6]-三角函数  [7]-最高阶数  [8]-变量替换式
# 对应值  0 不包含 1 化简后包含  -1 原来包含化简后不包含
def pre_simplify(eq, flag=[0, 0, 0, 0, 0, 0, 0, 0, 0]):
    def update_pow(var_base, var_index, flag):
        if var_base.is_Pow and var_base.args[1] * var_index == 1 and var_index.is_even:
            expr = var_base.args[0]
            flag[3] = -1
            if var_base.args[1].is_even:
                expr = Abs(var_base.args[0])
                flag[4] = 1
        else:
            expr = Pow(var_base, var_index)
        return expr

    if isinstance(eq, (Symbol, Number)):
        expr = eq
        return expr
    if len(eq.args) > 0:
        if eq.is_Pow:
            if eq.args[0].is_Mul:  # [log(x,2)]**2 -> {[log(2)**(-1)]*log(x)}**2
                if isinstance(eq.args[0].args[1], log) and len(eq.args[0].args[1].args[0].free_symbols) > 0:
                    flag[5] = 2
                    flag[8] = eq.args[0]
            elif isinstance(eq.args[0], (sin, cos, tan, cot)):
                flag[6] = 2
                flag[8] = eq.args[0]
            var_base = pre_simplify(eq.args[0], flag)
            var_index = pre_simplify(eq.args[1], flag)
            expr = update_pow(var_base, var_index, flag)
            if expr.is_Pow:
                if len(expr.args[1].free_symbols) > 0:  # 2**(2*x) or  (x-1)**(x+2)
                    if len(expr.args[0].free_symbols) > 0:
                        flag[0] = 1
                    else:
                        flag[2] = 1
                else:  # sqrt(x+1) or (x+2)**(-1)
                    if len(expr.args[0].free_symbols) > 0:
                        if Abs(1 / expr.args[1]).is_even:
                            flag[3] = 1
                        elif expr.args[1] < 0:
                            flag[1] = 1
                            if not flag[2] and not flag[5] and not flag[6]:
                                flag[8] = expr.args[0]
        elif eq.is_Add:
            expr = pre_simplify(eq.args[0], flag)
            for i in range(1, len(eq.args)):
                expr = Add(expr, pre_simplify(eq.args[i], flag))
            if not flag[0] and not flag[2] and not flag[5]:
                expr = expr
            else:
                expr = factor(expr)
        elif eq.is_Mul:
            expr = pre_simplify(eq.args[0], flag)
            for i in range(1, len(eq.args)):
                expr = Mul(expr, pre_simplify(eq.args[i], flag))
            if flag[1] == 1 and flag[5] == 0:
                expr = factor(cancel(expr))
                flag[1] = -1
                for v in expr.args:
                    if v.is_Pow and v.args[1] == -1:
                        flag[1] = 1
            else:
                expr = expr

        elif isinstance(eq, Abs):
            expr = Abs(pre_simplify(eq.args[0], flag))
            flag[4] = 1
        elif isinstance(eq, log):
            expr = log(pre_simplify(eq.args[0], flag))
            if flag[5] == 0:
                flag[5] = 1
        elif isinstance(eq, (sin, cos, tan, cot)):
            expr = type(eq)(pre_simplify(eq.args[0], flag))
            if len(expr.args[0].free_symbols) > 0:
                if expr.args[0].is_Symbol:  # sin(x)
                    if flag[6] == 0:
                        flag[6] = 1
                        flag[8] = eq
                    elif flag[6] == 2 or type(eq) != type(flag[8]):  # sin(2*x) + sin(x)
                        flag[6] = -1
                        flag[8] = eq
                else:  # sin(2*x)
                    if flag[6] == 1 and type(eq) != type(flag[8]):  # sin(x) + cos(x)
                        flag[6] = -1
                    elif flag[6] == 2 and type(eq) != type(flag[8]):  # sin(2*x) + sin(3*x)  or sin(2*x) + cos(2*x)
                        flag[6] = -1
                        flag[8] = expr
                    else:  # sin(2*x)
                        flag[6] = 2
                        flag[8] = expr.args[0]
        elif isinstance(eq, (asin, acos, atan, acot)):
            expr = type(eq)(pre_simplify(eq.args[0], flag))
            flag[6] = -2
            flag[8] = eq
        return expr


if __name__ == '__main__':
    pass
